/************************************************************
 * Project Name         [Thinking_In_Java]
 * File Name            [Producer_Consumer_V1.java]
 * Creation Date        [04-Jul-2014]
 * 
 * Copyright© ge.y.yang@gmail.com All Rights Reserved
 * 
 * Work hard, play harder, think big and keep fit
 ************************************************************/
package pkg_08_thread.producer_consumer;

import java.util.LinkedList;

/**
 * 生产者消费者模式 1 - 使用wait()/notifyAll()
 * 
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 * 
 */
public class Producer_Consumer_V1 {

	/**
	 * 测试方法
	 * 
	 * @param args
	 *            命令行参数
	 */
	public static void main(String[] args) {
		Warehouse_V1 warehouse = new Warehouse_V1();

		Producer p1 = new Producer(warehouse, 10);
		Producer p2 = new Producer(warehouse, 30);
		Producer p3 = new Producer(warehouse, 20);
		Producer p4 = new Producer(warehouse, 50);
		Producer p5 = new Producer(warehouse, 40);

		Consumer c1 = new Consumer(warehouse, 50);
		Consumer c2 = new Consumer(warehouse, 20);
		Consumer c3 = new Consumer(warehouse, 70);

		c1.start();
		c2.start();
		c3.start();
		p1.start();
		p2.start();
		p3.start();
		p4.start();
		p5.start();
	}
}

/**
 * 仓库类
 * 
 * @author 不落的太阳(Sean Yang)
 * @version 1.0
 * @since JDK 6
 * 
 */
class Warehouse_V1 implements Warehouse {

	// 仓库最大的存储量
	private static final int MAX_SIZE = 100;

	// 仓库的载体
	private LinkedList<String> list = new LinkedList<String>();

	/**
	 * 生产方法
	 * 
	 * @throws InterruptedException
	 */
	@Override
	public void produce(int number) throws InterruptedException {
		synchronized (list) {
			// 如果仓库容量不足
			while (list.size() + number > MAX_SIZE) {
				System.out.println("[要生产的产品数量]: " + number + "\t[库存量]: "
						+ list.size() + "\t暂时不能执行生产任务.");
				// 不能满足生产, 产生阻塞
				list.wait();
			}

			// 生产条件满足, 生产number个产品
			for (int i = 1; i <= number; i++) {
				list.add(new String("产品" + i));
			}
			System.out.println("[已经生产的产品数量]: " + number + "\t[库存量]: "
					+ list.size());
			list.notifyAll();
		}
	}

	/**
	 * 消费方法
	 * 
	 * @return
	 * @throws InterruptedException
	 */
	@Override
	public synchronized void consume(int number) throws InterruptedException {
		synchronized (list) {
			// 库存不足, 不能消费
			while (list.size() < number) {
				System.out.println("[要消费的产品数量]: " + number + "\t[库存量]: "
						+ list.size() + "\t暂时不能执行消费任务.");
				// 不能满足消费, 产生阻塞
				list.wait();
			}

			// 消费满足的情况下, 消费number个产品
			for (int i = 1; i <= number; i++) {
				list.remove();
			}
			System.out.println("[已消费的产品数量]: " + number + "\t[库存量]: "
					+ list.size());
			list.notifyAll();
		}
	}
}
